"""Generate and work with PEP 425 Compatibility Tags. """ from __future__ import absolute_import import logging import re from pip._vendor.packaging.tags import ( Tag, compatible_tags, cpython_tags, generic_tags, interpreter_name, interpreter_version, mac_platforms, ) from pip._internal.utils.typing import MYPY_CHECK_RUNNING if MYPY_CHECK_RUNNING: from typing import List, Optional, Tuple from pip._vendor.packaging.tags import PythonVersion logger = logging.getLogger(__name__) _osx_arch_pat = re.compile(r'(.+)_(\d+)_(\d+)_(.+)') def version_info_to_nodot(version_info): # type: (Tuple[int, ...]) -> str # Only use up to the first two numbers. return ''.join(map(str, version_info[:2])) def _mac_platforms(arch): # type: (str) -> List[str] match = _osx_arch_pat.match(arch) if match: name, major, minor, actual_arch = match.groups() mac_version = (int(major), int(minor)) arches = [ # Since we have always only checked that the platform starts # with "macosx", for backwards-compatibility we extract the # actual prefix provided by the user in case they provided # something like "macosxcustom_". It may be good to remove # this as undocumented or deprecate it in the future. '{}_{}'.format(name, arch[len('macosx_'):]) for arch in mac_platforms(mac_version, actual_arch) ] else: # arch pattern didn't match (?!) arches = [arch] return arches def _custom_manylinux_platforms(arch): # type: (str) -> List[str] arches = [arch] arch_prefix, arch_sep, arch_suffix = arch.partition('_') if arch_prefix == 'manylinux2014': # manylinux1/manylinux2010 wheels run on most manylinux2014 systems # with the exception of wheels depending on ncurses. PEP 599 states # manylinux1/manylinux2010 wheels should be considered # manylinux2014 wheels: # https://www.python.org/dev/peps/pep-0599/#backwards-compatibility-with-manylinux2010-wheels if arch_suffix in {'i686', 'x86_64'}: arches.append('manylinux2010' + arch_sep + arch_suffix) arches.append('manylinux1' + arch_sep + arch_suffix) elif arch_prefix == 'manylinux2010': # manylinux1 wheels run on most manylinux2010 systems with the # exception of wheels depending on ncurses. PEP 571 states # manylinux1 wheels should be considered manylinux2010 wheels: # https://www.python.org/dev/peps/pep-0571/#backwards-compatibility-with-manylinux1-wheels arches.append('manylinux1' + arch_sep + arch_suffix) return arches def _get_custom_platforms(arch): # type: (str) -> List[str] arch_prefix, arch_sep, arch_suffix = arch.partition('_') if arch.startswith('macosx'): arches = _mac_platforms(arch) elif arch_prefix in ['manylinux2014', 'manylinux2010']: arches = _custom_manylinux_platforms(arch) else: arches = [arch] return arches def _get_python_version(version): # type: (str) -> PythonVersion if len(version) > 1: return int(version[0]), int(version[1:]) else: return (int(version[0]),) def _get_custom_interpreter(implementation=None, version=None): # type: (Optional[str], Optional[str]) -> str if implementation is None: implementation = interpreter_name() if version is None: version = interpreter_version() return "{}{}".format(implementation, version) def get_supported( version=None, # type: Optional[str] platform=None, # type: Optional[str] impl=None, # type: Optional[str] abi=None # type: Optional[str] ): # type: (...) -> List[Tag] """Return a list of supported tags for each version specified in `versions`. :param version: a string version, of the form "33" or "32", or None. The version will be assumed to support our ABI. :param platform: specify the exact platform you want valid tags for, or None. If None, use the local system platform. :param impl: specify the exact implementation you want valid tags for, or None. If None, use the local interpreter impl. :param abi: specify the exact abi you want valid tags for, or None. If None, use the local interpreter abi. """ supported = [] # type: List[Tag] python_version = None # type: Optional[PythonVersion] if version is not None: python_version = _get_python_version(version) interpreter = _get_custom_interpreter(impl, version) abis = None # type: Optional[List[str]] if abi is not None: abis = [abi] platforms = None # type: Optional[List[str]] if platform is not None: platforms = _get_custom_platforms(platform) is_cpython = (impl or interpreter_name()) == "cp" if is_cpython: supported.extend( cpython_tags( python_version=python_version, abis=abis, platforms=platforms, ) ) else: supported.extend( generic_tags( interpreter=interpreter, abis=abis, platforms=platforms, ) ) supported.extend( compatible_tags( python_version=python_version, interpreter=interpreter, platforms=platforms, ) ) return supported